﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Data;

namespace GeneralDataAccess {
    public static class DataTransformer {
        /// <summary>
        /// Realiza la conversión de un DataTable a 
        /// una lista genérica de tipo TargetType
        /// </summary>
        /// <typeparam name="TargetType">Tipo destino de la lista</typeparam>
        /// <param name="table">Origen de datos</param>
        /// <returns>Lista genérica</returns>
        /// <exception cref="Exception: En caso que los tipos del origen de datos no coincidan 
        /// con los de TargetType"></exception>
        public static List<TargetType> DataTableToGenericList<TargetType>(DataTable table) {
            List<TargetType> resultList = new List<TargetType>();
            DataColumn temp;
            TargetType item;

            item = Activator.CreateInstance<TargetType>();
            PropertyInfo[] properties = item.GetType().GetProperties();

            foreach (DataRow row in table.Rows) {
                item = Activator.CreateInstance<TargetType>();
                foreach (PropertyInfo property in properties) {
                    temp = table.Columns[property.Name];
                    if (temp != null) {
                        if (temp.DataType.Name.Equals(property.PropertyType.Name)) {
                            
                            if (!(row[temp] is DBNull))
                                property.SetValue(item, row[temp], null);
                        }
                        else {
                            throw new Exception("El tipo de la propiedad y columna son diferentes.");
                        }
                    }
                }
                resultList.Add(item);
            }
            return resultList;
        }
        /// <summary>
        /// Realiza la conversión de un IDataReader a 
        /// una lista genérica de tipo TargetType
        /// </summary>
        /// <typeparam name="TargetType">Tipo destino de la lista</typeparam>
        /// <param name="reader">Origen de datos</param>
        /// <returns>Lista genérica</returns>
        /// <exception cref="Exception: En caso que los tipos del origen de datos no coincidan 
        /// con los de TargetType"></exception>
        public static List<TargetType> DataReaderToGenericList<TargetType>(IDataReader reader) {
            List<TargetType> resultList = new List<TargetType>();
            object propertyValue;
            int columnNumber = reader.FieldCount;
            TargetType item;

            item = Activator.CreateInstance<TargetType>();
            PropertyInfo[] properties = item.GetType().GetProperties();

            while (reader.Read()) {
                item = Activator.CreateInstance<TargetType>();
                foreach (PropertyInfo property in properties) {
                    for (int i = 0; i < columnNumber; i++) {
                        if (reader.GetName(i).ToLower().Equals(property.Name.ToLower())) {
                            if (reader.GetFieldType(i).Name.Equals(property.PropertyType.Name)) {
                                propertyValue = reader.GetValue(i);
                                property.SetValue(item, propertyValue, null);
                                break;
                            }
                            else {
                                throw new Exception("El tipo de la propiedad y columna son diferentes.");
                            }
                        }
                    }
                }
                resultList.Add(item);
            }
            return resultList;
        }

        public static TargetType DataTableToObject<TargetType>(DataTable table) {
            List<TargetType> lista = DataTableToGenericList<TargetType>(table);
            if (lista.Count > 0)
                return lista[0];
            else
                return default(TargetType);
        }
    }
}
